﻿Imports System.Data.SqlClient
Imports SharedCode.PublicEnums
Imports SharedCode.SQLServerObjects
Imports System.Messaging
Imports SharedCode.Impersonation


<AttributeUsage(AttributeTargets.All, Inherited:=True)> _
Public Class ServiceBroker
    Inherits Attribute

    Private _ServerName As String
    Private _DatabaseName As String
    Private _UserName As String
    Private _Password As String
    Private _AuthenticationType As SQL_Authentication_Type
    Private _MessageBodyDataType As SQL_ServiceBroker_MessageBody_DataType
    Private _MessageType As String
    Private _MessageTypeEndConveration As String
    Private _Contract As String
    Private _Queue As String
    Private _ServiceSource As String
    Private _ServiceDestination As String
    Private _ConversationEncryption As Boolean
    Private _SingleMessagePerConversation As Boolean
    Private _MessagesPerConversation As Integer
    Private _MessagesSent As Integer
    Private _ConversationHandle As Guid

    Public Property MessageType() As String
        Get
            Return _MessageType
        End Get
        Set(ByVal value As String)
            _MessageType = value
        End Set
    End Property
    Public Property MessageTypeEndConversation() As String
        Get
            Return _MessageTypeEndConveration
        End Get
        Set(ByVal value As String)
            _MessageTypeEndConveration = value
        End Set
    End Property
    Public Property Contract() As String
        Get
            Return _Contract
        End Get
        Set(ByVal value As String)
            _Contract = value
        End Set
    End Property
    Public Property Queue() As String
        Get
            Return _Queue
        End Get
        Set(ByVal value As String)
            _Queue = value
        End Set
    End Property
    Public Property ServiceSource() As String
        Get
            Return _ServiceSource
        End Get
        Set(ByVal value As String)
            _ServiceSource = value
        End Set
    End Property
    Public Property ServiceDestination() As String
        Get
            Return _ServiceDestination
        End Get
        Set(ByVal value As String)
            _ServiceDestination = value
        End Set
    End Property
    Public Property SingleMessagePerConversation() As Boolean
        Get
            Return _SingleMessagePerConversation
        End Get
        Set(ByVal value As Boolean)
            _SingleMessagePerConversation = value
        End Set
    End Property
    Public Property ConversationEncryption() As Boolean
        Get
            Return _ConversationEncryption
        End Get
        Set(ByVal value As Boolean)
            _ConversationEncryption = value
        End Set
    End Property
    Public Property MessagesPerConversation() As Integer
        Get
            Return _MessagesPerConversation
        End Get
        Set(ByVal value As Integer)
            If _SingleMessagePerConversation = True Then _MessagesPerConversation = 1
            _MessagesPerConversation = value
        End Set
    End Property
    Public ReadOnly Property MessagesSent() As Integer
        Get
            Return _MessagesSent
        End Get
    End Property
    Public Property ServerName() As String
        Get
            Return _ServerName
        End Get
        Set(ByVal value As String)
            _ServerName = value
        End Set
    End Property
    Public Property MessageBodyDataType() As SQL_ServiceBroker_MessageBody_DataType
        Get
            Return _MessageBodyDataType
        End Get
        Set(ByVal value As SQL_ServiceBroker_MessageBody_DataType)
            _MessageBodyDataType = value
        End Set
    End Property
    Public ReadOnly Property ConversationHandle() As Guid
        Get
            Return _ConversationHandle
        End Get
    End Property
    Public ReadOnly Property ConnectionString() As String
        Get
            Return SQLConnectionString(_ServerName, _DatabaseName, _AuthenticationType, _UserName, _Password)
        End Get
    End Property
    Public ReadOnly Property StartNewConversation() As Boolean
        Get
            If MessagesSent = MessagesPerConversation Then
                Return True
            Else
                If ConversationHandle = Nothing Then
                    Return True
                Else
                    Return False
                End If
            End If
        End Get
    End Property
    Public ReadOnly Property EndConversation() As Boolean
        Get
            If MessagesSent = MessagesPerConversation Then
                Return True
            Else
                Return False
            End If
        End Get
    End Property
    Public Sub SendMessage(ByVal MessageBody)
        Dim SQLCmd As SqlCommand

        If StartNewConversation = True Then
            If ConversationHandle <> Nothing Then
                If MessageTypeEndConversation <> Nothing Then
                    SQLCmd = New SqlCommand
                    SQLCmd.CommandText = "SEND ON CONVERSATION '" + ConversationHandle.ToString + "' MESSAGE TYPE [" + MessageTypeEndConversation + "];"
                    SQLCmd.CommandType = CommandType.Text
                    SQLRunCommand_NoResultSet(SQLCmd, ConnectionString)
                End If
                _ConversationHandle = Nothing
            End If
            SQLCmd = New SqlCommand
            SQLCmd.CommandText = "BEGIN DIALOG @conversation_handle FROM SERVICE [" + ServiceSource + "] TO SERVICE '" + ServiceDestination + "' ON CONTRACT [" + Contract + "], ENCRYPTION="
            If ConversationEncryption = True Then
                SQLCmd.CommandText += "ON;"
            Else
                SQLCmd.CommandText += "OFF;"
            End If
            SQLCmd.CommandType = CommandType.Text
            SQLCmd.Parameters.Add("@conversation_handle", SqlDbType.UniqueIdentifier)
            SQLCmd.Parameters.Item("@conversation_handle").Direction = ParameterDirection.Output
            SQLRunCommand_NoResultSet(SQLCmd, ConnectionString)
            _ConversationHandle = SQLCmd.Parameters.Item("@conversation_handle").Value
            _MessagesSent = 0
        End If

        SQLCmd = New SqlCommand
        If MessageBodyDataType = SQL_ServiceBroker_MessageBody_DataType.Empty Then
            SQLCmd.CommandText = "SEND ON CONVERSATION '" + ConversationHandle.ToString + "' MESSAGE TYPE [" + MessageType + "]'"
        Else
            SQLCmd.CommandText = "SEND ON CONVERSATION '" + ConversationHandle.ToString + "' MESSAGE TYPE [" + MessageType + "] (@message_body);'"
        End If
        SQLCmd.CommandType = CommandType.Text
        If MessageBodyDataType = SQL_ServiceBroker_MessageBody_DataType.NVARCHAR Then
            SQLCmd.Parameters.Add("@message_body", SqlDbType.VarChar, 8000)
        ElseIf MessageBodyDataType = SQL_ServiceBroker_MessageBody_DataType.VARBINARY Then
            SQLCmd.Parameters.Add("@message_body", SqlDbType.VarBinary, 8000)
        ElseIf MessageBodyDataType = SQL_ServiceBroker_MessageBody_DataType.NVARCHAR Then
            SQLCmd.Parameters.Add("@message_body", SqlDbType.NVarChar, 4000)
        ElseIf MessageBodyDataType = SQL_ServiceBroker_MessageBody_DataType.XML Then
            SQLCmd.Parameters.Add("@message_body", SqlDbType.Xml)
        End If
        SQLCmd.Parameters.Item("@message_body").Direction = ParameterDirection.Input
        SQLCmd.Parameters.Item("@message_body").Value = MessageBody
        SQLRunCommand_NoResultSet(SQLCmd, ConnectionString)

        SQLCmd.Dispose()

        _MessagesSent += 1

        If EndConversation = True Then
            _MessagesSent = 0
            _ConversationHandle = Nothing
        End If


    End Sub
    Public Sub ReceiveMessage(ByRef message_body)
        Dim SQLCmd As SqlCommand
        Dim conversation_handle As Guid
        Dim message_type_name As String
        SQLCmd = New SqlCommand
        SQLCmd.CommandText = "WAITFOR (RECEIVE TOP (1) @conversation_handle = conversation_handle, @message_type_name = message_type_name, @message_body = message_body FROM [" + Queue + "]), DELAY 1000"
        SQLCmd.CommandType = CommandType.Text
        SQLCmd.Parameters.Add("@conversation_handle")
        SQLCmd.Parameters.Add("@message_type_name")
        SQLCmd.Parameters.Add("@message_body")
        SQLCmd.Parameters.Item("@conversation_handle").Direction = ParameterDirection.Output
        SQLCmd.Parameters.Item("@message_type_name").Direction = ParameterDirection.Output
        SQLCmd.Parameters.Item("@message_body").Direction = ParameterDirection.Output

        SQLRunCommand_NoResultSet(SQLCmd, ConnectionString)

        conversation_handle = SQLCmd.Parameters.Item("@conversation_handle").Value
        message_type_name = SQLCmd.Parameters.Item("@message_type_name").Value
        message_body = SQLCmd.Parameters.Item("@message_body").Value

        If (message_type_name = MessageTypeEndConversation And message_type_name <> "") Or MessagesPerConversation = 1 Then
            SQLCmd = New SqlCommand
            SQLCmd.CommandText = "END CONVERSATION '" + conversation_handle.ToString + "'"
            SQLRunCommand_NoResultSet(SQLCmd, ConnectionString)
        End If
    End Sub

End Class

<AttributeUsage(AttributeTargets.All, inherited:=True)> _
Public Class MSMQ
    Inherits Attribute

    Private _ServerName As String
    Private _QueueName As String
    Private _IsTransactional As Boolean
    Private _IsPrivateQueue As Boolean
    Private _UserName As String
    Private _Password As String
    Private _ResendOnFailure As String
    Public Property UserName() As String
        Get
            Return _UserName
        End Get
        Set(ByVal value As String)
            _UserName = value
        End Set
    End Property
    Public Property Password() As String
        Get
            Return _Password
        End Get
        Set(ByVal value As String)
            _Password = value
        End Set
    End Property
    Public Property ServerName() As String
        Get
            Return _ServerName
        End Get
        Set(ByVal value As String)
            _ServerName = value
        End Set
    End Property
    Public Property QueueName() As String
        Get
            Return _QueueName
        End Get
        Set(ByVal value As String)
            _QueueName = value
        End Set
    End Property
    Public Property ResendOnFailure() As String
        Get
            Return _ResendOnFailure
        End Get
        Set(ByVal value As String)
            _ResendOnFailure = value

        End Set
    End Property
    Public Property IsPrivateQueue() As Boolean
        Get
            Return _IsPrivateQueue
        End Get
        Set(ByVal value As Boolean)
            _IsPrivateQueue = value
        End Set
    End Property
    Public Property IsTransactional() As Boolean
        Get
            Return _IsTransactional
        End Get
        Set(ByVal value As Boolean)
            _IsTransactional = value
        End Set
    End Property
    Public ReadOnly Property FullQueueName() As String
        Get
            If IsPrivateQueue = True Then
                Return "FormatName:Direct=OS:" + ServerName + "\\private$\\" + QueueName
            Else
                Return "FormatName:Direct=OS:" + ServerName + "\\public$\\" + QueueName
            End If
        End Get
    End Property
    Public Sub SendMessage(ByVal message_body)
        Dim MsgQueue As MessageQueue
        Dim aa As New Impersonation(UserName, Password)
        aa.BeginImpersonation()
        MsgQueue = New MessageQueue(FullQueueName)
        If IsTransactional = True Then
            MsgQueue.Send(message_body, MessageQueueTransactionType.Single)
        Else
            MsgQueue.Send(message_body, MessageQueueTransactionType.None)
        End If
        aa.EndImpersonation()

    End Sub
    Public Sub ReceiveMessage(ByRef message_body)
        Dim MsgQueue As MessageQueue
        Dim aa As New Impersonation(UserName, Password)
        aa.BeginImpersonation()
        MsgQueue = New MessageQueue(FullQueueName)
        message_body = MsgQueue.Receive()
        aa.EndImpersonation()

    End Sub
End Class
